<?php
/**
 * Created by PhpStorm.
 * Date: 2022/4/18
 * Time: 20:46
 */
namespace app\service;

use app\model\Flow;
use app\validate\FlowValidate;
use think\annotation\Inject;
use think\exception\ValidateException;
use think\facade\Db;

class FlowService
{
    /**
     * @Inject()
     * @var Flow
     */
    protected $flowModel;

    public function getFlowList($param)
    {
        $limit = $param['pageSize'];
        $where = [];

        if (!empty($param['name'])) {
            $where[] = ['name', 'like', '%' . $param['name'] . '%'];
        }

        return $this->flowModel->getPageList($limit, $where);
    }

    public function addFlow($param)
    {
        try {

            validate(FlowValidate::class)->check($param);
        } catch (ValidateException $e) {
            return dataReturn(-1, $e->getError());
        }

        if ($param['link_type'] == 1 && empty($param['form_id'])) {
            return dataReturn(-4, '请选择关联的表单');
        }

        if ($param['link_type'] == 3 && empty($param['table_name'])) {
            return dataReturn(-5, '请输入关联的表');
        }

        $has = $this->flowModel->checkUnique(['name' => $param['name']])['data'];
        if (!empty($has)) {
            return dataReturn(-2, '该流程已经存在');
        }

        $where[] = ['table_name' => $param['table_name']];
        $where[] = ['status', '=', 1];
        $hasBind = $this->flowModel->findOne($where, 'id')['data'];
        if (!empty($hasBind)) {
            return dataReturn(-3, '该表已绑定了流程，不可重复绑定。');
        }

        $param['status'] = 2;
        $param['code'] = uniqid();
        $param['create_time'] = date('Y-m-d H:i:s');

        return $this->flowModel->insertOne($param);
    }

    public function editFlow($param)
    {
        try {

            validate(FlowValidate::class)->check($param);
        } catch (ValidateException $e) {
            return dataReturn(-1, $e->getError());
        }

        if ($param['link_type'] == 1 && empty($param['form_id'])) {
            return dataReturn(-4, '请选择关联的表单');
        }

        if ($param['link_type'] == 3 && empty($param['table_name'])) {
            return dataReturn(-5, '请输入关联的表');
        }

        $has = $this->flowModel->checkUnique(['name' => $param['name']], $param['id'])['data'];
        if (!empty($has)) {
            return dataReturn(-2, '该流程已经存在');
        }

        $where[] = ['table_name' => $param['table_name']];
        $where[] = ['id', '<>', $param['id']];
        $where[] = ['status', '=', 1];
        $hasBind = $this->flowModel->findOne($where, 'id')['data'];
        if (!empty($hasBind)) {
            return dataReturn(-3, '该表已绑定了流程，不可重复绑定。');
        }

        $param['update_time'] = date('Y-m-d H:i:s');

        return $this->flowModel->updateById($param, $param['id']);
    }

    public function showTableColumn($param)
    {
        $table = $param['table'];
        if ($param['link_type'] == 1) {
            $table = makeTable($param['table'] . '_auto');
        } else if ($param['link_type'] == 3) {
            $table = makeTable($param['table']);
        }

        try {

            $fieldMap = [];
            $fields = Db::getFields($table);

            foreach ($fields as $key => $vo) {

                $fieldMap[] = [
                    'label' => $vo['comment'],
                    'value' => $vo['name']
                ];
            }
        } catch (\Exception $e) {

            return dataReturn(-1, $e->getMessage());
        }

        return dataReturn(0, 'success', $fieldMap);
    }

    public function updateFlowStatus($id, $status)
    {
        $info = $this->flowModel->findOne(['id' => $id])['data'];
        if (empty($info['design_content'])) {
            return dataReturn(-6, '请先完成设计！');
        }

        // 部署
        if ($status == 1) {
            // 检测是否要追加流程状态字段
            $res = $this->checkAndAddColumn($info['table_name'], $info['link_type']);
            if ($res['code'] == -1) {
                return dataReturn(-4, '绑定的表异常');
            }
        } else {

            // 卸载
            $res = $this->checkAndDropColumn($info['table_name'], $info['link_type']);
            if ($res['code'] == -1) {
                return dataReturn(-4, '绑定的表异常');
            }
        }

        return $this->flowModel->updateById([
            'status' => $status,
            'update_time' => date('Y-m-d H:i:s')
        ], $id);
    }

    private function checkAndAddColumn($table, $linkType)
    {
        try {

            if ($linkType == 1) {
                $table = makeTable($table . '_auto');
            } else if ($linkType == 3) {
                $table = makeTable($table);
            }

            $sql = "ALTER TABLE `" . $table . "` ";

            $has = Db::execute('desc `' . $table . '` `flow_status`');
            if (!$has) {
                $comment = '流程状态';
                foreach (config('flow.flow_status') as $key => $vo) {
                    $comment .= ' ' . $key . ':' . $vo;
                }

                $sql .= "ADD COLUMN `flow_status` tinyint(2) NULL DEFAULT 1 COMMENT '" . $comment . "',";
            } else {
                return dataReturn(-2, '该表flow_status字段已经存在,请联系管理员');
            }

            $has = Db::execute('desc `' . $table . '` `flow_operator_id`');
            if (!$has) {
                $comment = '流程提交人';
                $sql .= "ADD COLUMN `flow_operator_id` int(11) NULL DEFAULT 0 COMMENT '" . $comment . "';";
            } else {
                return dataReturn(-3, '该表flow_operator_id字段已经存在,请联系管理员');
            }

            Db::query($sql);
        } catch (\Exception $e) {
            return dataReturn(-1, $e->getMessage());
        }

        return dataReturn(0, 'success');
    }

    private function checkAndDropColumn($table, $linkType)
    {
        try {

            if ($linkType == 1) {
                $table = makeTable($table . '_auto');
            } else if ($linkType == 3) {
                $table = makeTable($table);
            }

            $sql = "ALTER TABLE `" . $table . "` ";
            $sql .= 'DROP COLUMN `flow_status`,';
            $sql .= 'DROP COLUMN `flow_operator_id`;';
            Db::query($sql);
        } catch (\Exception $e) {
            return dataReturn(-1, $e->getMessage());
        }

        return dataReturn(0, 'success');
    }
}